package win.bitterwine.BasicService;

import org.smart4j.framework.dao.DatabaseHelper;
import org.smart4j.framework.dao.SqlHelper;
import org.smart4j.framework.orm.DataSet;
import org.smart4j.framework.tx.annotation.Service;
import org.smart4j.framework.tx.annotation.Transaction;
import org.smart4j.framework.util.MapUtil;
import org.smart4j.framework.util.ObjectUtil;
import win.bitterwine.bean.cache.CacheInter;
import win.bitterwine.bean.cache.RedisCache;
import win.bitterwine.util.PublicTool;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2017/6/20.
 */
@Service
public class BasicServiceImpl implements BasicService {

    private CacheInter cache = new RedisCache();


    @Transaction
    public long save(Class<?> cls, Map<String, Object> fieldMap) {
        if (MapUtil.isEmpty(fieldMap)) {
            return 0;
        }
        String sql = SqlHelper.generateInsertSql(cls, fieldMap.keySet());
        //int rows = DatabaseHelper.update(sql, fieldMap.values().toArray());
        long serializable = (long)DatabaseHelper.insertReturnPK(sql, fieldMap.values().toArray());
        Object obj = returnObj(cls, fieldMap, serializable);
        cache.saveOne(obj, serializable, true);
        return serializable;
    }

    /**
     * 通过反射,返回要缓存的对象
     * @param cls
     * @return
     */
    private Object returnObj(Class<?> cls, Map<String, Object> fieldMap, long id){
        //应该先获取该对象的所有字段,如果有值则在map中取值,如果没有则设置该字段应有的初始值
        Object newInstance = ObjectUtil.newInstance(cls.getName());
        ObjectUtil.setField(newInstance, "id", id);
        Map<String, String> map = PublicTool.getFiledsMap(cls);
        for(String mapKey : map.keySet()){
            //如果表单参数中存在该字段,则将值赋给该字段,否则根据值类型付给初始值
            if(fieldMap.keySet().contains(mapKey)){
                ObjectUtil.setField(newInstance, mapKey, fieldMap.get(mapKey));
            }else{
                //根据类型赋初始值
                String type = map.get(mapKey);
                if(type.contains("int") || type.contains("Integer") || type.contains("long") || type.contains("Long")){
                    ObjectUtil.setField(newInstance, mapKey, 0);
                }else if(type.contains("Date")){
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    ObjectUtil.setField(newInstance, mapKey, sdf.format(new Date()));
                }else {
                    ObjectUtil.setField(newInstance, mapKey, "");
                }
            }
        }
        return newInstance;
    }

    /**
     * 插入一个实体
     */
    public long save(Object entity){
        if (entity == null) {
            throw new IllegalArgumentException();
        }
        Class<?> entityClass = entity.getClass();
        Map<String, Object> fieldMap = ObjectUtil.getFieldMap(entity);
        return save(entityClass, fieldMap);
    }
    //

    /**
     * 更新相关数据
     */
    @Transaction
    public boolean update(Class<?> entityClass, Map<String, Object> fieldMap, String condition, Object... params){
        boolean update = updateDB(entityClass, fieldMap, condition, params);
        if(update){ //更新成功
            //更新缓存分两种情况
            if(condition.equals("id=?")){
                // 1.修改的条件为 id=?
                long id = Long.parseLong(params[0].toString());
                //Object obj = findById(entityClass, id);
                //删除缓存中的该记录
                cache.delete(PublicTool.getsubTableName(entityClass.getName())+"_"+id);
                findById(entityClass, id);
            }else{ //不建议使用非id修改方式
                // 2.其他条件修改(有可能修改多条数据),删除与该表相关的所有记录
               cache.delete(entityClass);
            }
        }
        return update;
    }
    public  boolean update(Class<?> cls, long id, Map<String, Object> fieldMap) {
        boolean update = update(cls, fieldMap, "id=?", id);
        return update;
    }
    @Transaction
    private boolean updateDB(Class<?> entityClass, Map<String, Object> fieldMap, String condition, Object... params){
        boolean update = DataSet.update(entityClass, fieldMap, condition, params);
        return update;
    }

    /**
     * 删除相关数据
     */
    @Transaction
    public boolean delete(Class<?> entityClass, String condition, Object... params){
        boolean delete = deleteDB(entityClass, condition, params);
        if(delete){
            //分俩种情况
            if(condition.equals("id=?")){
                //1.根据id删除
                cache.delete(PublicTool.getsubTableName(entityClass.getName())+"_"+params[0]);
                cache.deleteNo(entityClass);//删除相关缓存
            }else{
                //有可能是多条删除
                cache.delete(entityClass);//删除相关缓存
            }
        }
        return delete;
    }

    public boolean delete(Class<?> cls, long id) {
        boolean delete = delete(cls, "id=?", id);
        return delete;
    }

    @Transaction
    public boolean deleteDB(Class<?> entityClass, String condition, Object... params){
        boolean delete = DataSet.delete(entityClass, condition, params);
        return delete;
    }


    /*-------------------------------------新加---------------------------------------------*/

    /**
     * 根据条件查询单个对象
     * @param entityClass
     * @param condition
     * @param params
     * @param <T>
     * @return
     */
    public <T> T selectOneObj(Class<T> entityClass, String condition, Object... params){
        T t = null;
        String oneKey = PublicTool.getCacheOneKey(entityClass, condition, params);
        if(cache.isExists(oneKey)){
            t = (T)cache.getOneObject(entityClass, oneKey);
            System.out.println("selectOneObj>>>>>>>>>>>>>>>>[缓存中存在key<"+oneKey+">]");
        }else{
            t = selectOneObjDB(entityClass, condition, params);
            cache.putObjToRedis(oneKey, t);
            System.out.println("selectOneObj>>>>>>>>>>>>>>>>[缓存中不存在key<"+oneKey+">,现将结果存入redis.]");
        }
        return t;
    }

    /**
     * 根据id获取
     * @param cls
     * @param id
     * @param <T>
     * @return
     */
    public <T> Object findById(Class<T> cls, long id) {
        T t = selectOneObj(cls, "id=?", id);
        return t;
    }
    /**
     * 查询单条数据，并转为相应类型的实体
     */
    private <T> T selectOneObjDB(Class<T> entityClass, String condition, Object... params) {
        T t = DataSet.select(entityClass, condition, params);
        return t;
    }

//--------------------------------------下面是查询list的最基本方法--------------------------------------------------
    /**
     * 查询多条数据，并转为相应类型的实体列表（带有查询条件、排序方式与查询参数）
     *
     */
    public <T> List<T> selectListWithConditionAndSort(Class<T> entityClass, String condition, String sort, Object... params){
        List<Object> list = null;
        String listKey = PublicTool.getCacheSelectListKey(entityClass, condition, sort, params);
        if( cache.isExists(listKey) ){
            list = cache.getList(listKey);
            System.out.println("selectListWithConditionAndSort>>>>>>>>>>>>>>>>[缓存中存在key<"+listKey+">]");
            if(list.contains(null)){ //判断是否key被删除,重新查询获取
                cache.delete(listKey);
                list = (List<Object>) selectListWithConditionAndSortDB(entityClass, condition, sort, params);
                cache.putListToRedis(listKey, list);
                System.out.println("selectListWithConditionAndSort>>>>>>>>>>>>>>>>[缓存中存在key<"+listKey+">,但是存在null值,重新获取.]");
            }
        }else{
            list = (List<Object>) selectListWithConditionAndSortDB(entityClass, condition, sort, params);
            cache.putListToRedis(listKey, list);
            System.out.println("selectListWithConditionAndSort>>>>>>>>>>>>>>>>[缓存中不存在key<"+listKey+">,现将结果存入redis.]");
        }
        return (List<T>) list;
    }
    private <T> List<T> selectListWithConditionAndSortDB(Class<T> entityClass, String condition, String sort, Object... params){
        List<T> list = DataSet.selectListWithConditionAndSort(entityClass, condition, sort, params);
        return list;
    }
    /**
     * 查询多条数据，并转为相应类型的实体列表
     */
    public <T> List<T> selectList(Class<T> entityClass) {
        List<T> list = selectListWithConditionAndSort(entityClass, "", "");
        return list;
    }

    /**
     * 查询多条数据，并转为相应类型的实体列表（带有排序方式）
     */
    public <T> List<T> selectListWithSort(Class<T> entityClass, String sort) {
        List<T> list = selectListWithConditionAndSort(entityClass, "", sort);
        return list;
    }

    /**
     * 查询多条数据，并转为相应类型的实体列表（带有查询条件与查询参数）
     */
    public <T> List<T> selectListWithCondition(Class<T> entityClass, String condition, Object... params) {
        List<T> list = selectListWithConditionAndSort(entityClass, condition, "", params);
        return list;
    }
    //--------------------------------------下面是查询数量的最基本方法--------------------------------------------------
    public long selectCount(Class<?> entityClass, String condition, Object... params){
        long count = 0l;
        String countKey = "count"+PublicTool.getCacheCommonKey(entityClass, condition, params);
        if( cache.isExists(countKey) ){
            String string = cache.getString(countKey);
            count = Long.parseLong(string);
            System.out.println("selectCount>>>>>>>>>>>>>>>>[缓存中存在key<"+countKey+">]");
        }else{
            count = selectCountDB(entityClass, condition, params);
            cache.putStringToRedis(countKey, count+"");
            System.out.println("selectCount>>>>>>>>>>>>>>>>[缓存中不存在key<"+countKey+">,现将结果存入redis.]");
        }
        return count;
    }
    /**
     * 查询数据条数
     */
    private long selectCountDB(Class<?> entityClass, String condition, Object... params){
        long count = DataSet.selectCount(entityClass, condition, params);
        return count;
    }
    /**
     * 查询数据条数
     */
    public long selectCount(Class<?> entityClass){
        long count = selectCount(entityClass, "");
        return count;
    }
    //--------------------------------------下面是分页的最基本方法--------------------------------------------------
    /**
     * 查询多条数据，并转为列表（分页方式）
     */
    public <T> List<T> selectListForPager(int pageNumber, int pageSize, Class<T> entityClass, String condition, String sort, Object... params){
        List<T> list = null;
        String pageKey = "page" + pageNumber + pageSize+PublicTool.getCacheSelectListKey(entityClass, condition, sort, params);
        if( cache.isExists(pageKey) ){
            list = (List<T>) cache.getList(pageKey);
            System.out.println("selectListForPager>>>>>>>>>>>>>>>>[缓存中存在key<"+pageKey+">]");
        }else{
            list = selectListForPagerDB(pageNumber, pageSize, entityClass, condition, sort, params);
            cache.putListToRedis(pageKey, (List<Object>)list);
            System.out.println("selectListForPager>>>>>>>>>>>>>>>>[缓存中不存在key<"+pageKey+">,现将结果存入redis.]");
        }
        return list;
    }
    /**
     * 查询多条数据，并转为列表（分页方式）
     */
    public <T> List<T> selectListForPagerDB(int pageNumber, int pageSize, Class<T> entityClass, String condition, String sort, Object... params){
        List<T> list = DataSet.selectListForPager(pageNumber, pageSize, entityClass, condition, sort, params);
        return list;
    }
    /**
     * 查询多条数据，并转为列表（分页方式）
     */
    public <T> List<T> selectListForPager(int pageNumber, int pageSize, Class<T> entityClass, String condition, Object... params){
        List<T> list = selectListForPager(pageNumber, pageSize, entityClass, condition, "", params);
        return list;
    }
    /**
     * 查询多条数据，并转为列表（分页方式）
     */
    public <T> List<T> selectListForPager(int pageNumber, int pageSize, Class<T> entityClass){
        List<T> list = selectListForPager(pageNumber, pageSize, entityClass, "", "");
        return list;
    }

    /*========================================================下方方法暂时没做redis缓存=====================================================================*/

    /**
     * 查询多条数据，并转为映射
     */
    public <T> Map<Long, T> selectMap(Class<T> entityClass){
        Map<Long, T> longTMap = DataSet.selectMap(entityClass);
        return longTMap;
    }
    /**
     * 查询多条数据，并转为映射（带有查询条件与查询参数）
     */
    public <T> Map<Long, T> selectMapWithCondition(Class<T> entityClass, String condition, Object... params){
        Map<Long, T> longTMap = DataSet.selectMapWithCondition(entityClass, condition, params);
        return longTMap;
    }
    /**
     * 查询多条数据，并转为映射（带有查询条件、排序方式与查询参数）
     */
    public <T> Map<Long, T> selectMapWithConditionAndSort(Class<T> entityClass, String condition, String sort, Object... params){
        Map<Long, T> longTMap = DataSet.selectMapWithConditionAndSort(entityClass, condition, sort, params);
        return longTMap;
    }

}
